package crafex.engine.system;

import java.lang.reflect.InvocationTargetException;

@SuppressWarnings("rawtypes")
public class Command {
	
	Object object;
	String method;
	Class[] classarray;
	Object[] args;
	private boolean isVoid;
	
	/**
	 * this is a command to be added to the command console or for buttons to use
	 * WARNING this connstructor is to be used only with void methods
	 * @param objectWithMethod object conntaining the method
	 * @param methodName name of the method
	 */
	public Command(Object objectWithMethod, String methodName){
		this.object = objectWithMethod;
		this.method = methodName;
		isVoid = true;
	}
	
	/**
	 * this is a command to be added to the command console or for buttons to use
	 * WARNING this connstructor is to be used only with NON-void methods
	 * @param objectWithMethod object conntaining the method
	 * @param methodName name of the method
	 * @param argTypes an array of all the arg types ex. String.class
	 * @param defaultArgs default args used when the command is used with out args
	 */
	public Command(Object objectWithMethod, String methodName, Class[] argTypes, Object[] defaultArgs){
		this.object = objectWithMethod;
		this.method = methodName;
		this.classarray = argTypes;
		this.args = defaultArgs;
		isVoid = false;
	}
	
	/**
	 * this is a command to be added to the command console or for buttons to use
	 * @param objectWithMethod object conntaining the method
	 * @param methodName name of the method
	 * @param argTypes an array of all the arg types ex. String.class
	 * @param defaultArgs default args used when the command is used with out args
	 * @param isVoid this tells if the method is void or not
	 */
	public Command(Object objectWithMethod, String methodName, Class[] argTypes, Object[] defaultArgs, boolean isVoid){
		this.object = objectWithMethod;
		this.method = methodName;
		this.classarray = argTypes;
		this.args = defaultArgs;
		this.isVoid = isVoid;
	}
	
	
	
	public Object getObject() {
		return object;
	}

	public void setObject(Object object) {
		this.object = object;
	}

	public String getMethod() {
		return method;
	}

	public void setMethod(String method) {
		this.method = method;
	}

	public Class[] getClassarray() {
		return classarray;
	}

	public void setClassarray(Class[] classarray) {
		this.classarray = classarray;
	}

	public Object[] getArgs() {
		return args;
	}

	public void setArgs(Object[] args) {
		this.args = args;
	}
	
	public boolean isVoid(){
		return isVoid;
	}

	public void run(){
		try {
			object.getClass().getMethod(method, classarray).invoke(object, args);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}
	}
	
	public void run(Object[] args){
		
		Object[] f_args = new Object[this.args.length];
		
		for(int i = 0; i < this.args.length; i++){
			if(i < args.length){
				if(args[i] != null){
					f_args[i] = args[i];
				}else{
					f_args[i] = this.args[i];
				}
			}
		}
		
		try {
			object.getClass().getMethod(method, classarray).invoke(object, f_args);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}
	}
}
